package com.misboot.document.exception;

import cn.ewsd.common.utils.IntegerUtils;
import com.misboot.document.utils.Result;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cloud.context.config.annotation.RefreshScope;
import org.springframework.http.converter.HttpMessageConversionException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.RestControllerAdvice;

import javax.servlet.http.HttpServletRequest;


/**
 * 全局异常处理
 *
 * @Author 湖南佐佑时代科技有限公司
 * @Email service@zuoyo.com
 * @Date 2022-05-18 13:40:36
 */
@RefreshScope
@RestControllerAdvice
public class GlobalExceptionHandler {

    private static final Logger log = LoggerFactory.getLogger(GlobalExceptionHandler.class);

    private static final String ACCESS_DENIED_MSG = "无权限访问，请联系系统管理员！！！";

    private static final String SystemFullMessage = "系统异常，请联系系统管理员！！！";

    private static final String BizFullMessage = "业务异常，请联系系统管理员！！！";

    private static final String NullFullMessage = "空指针异常，请联系系统管理员！！！";

    private static final String RuntimeFullMessage = "运行时异常，请联系系统管理员！！！";

    private static final String HttpRequestMethodNot = "请求方式不支持，请联系系统管理员！！！";

    private static final String ExceptionFullMessage = "未知异常，请联系系统管理员！！！";

    /**
     * 是否显示详细异常信息  true 是  false 否
     */
    @Value("${misboot.common.exception:true}")
    public Boolean showFullMessage;

    /**
     * 处理系统异常 出现此异常说明系统遇到了问题
     */
    @ExceptionHandler(SystemException.class)
    public Result handleSystemException(SystemException e, HttpServletRequest request) {
        log.error("请求地址{}发生系统异常:", request.getRequestURI(), e);
        return Result.ofFailMsg(showFullMessage ? e.getMessage() : SystemFullMessage);
    }

    /**
     * 处理业务异常  出现此异常说明业务出现异常，但不是致命异常，还可以继续进行运行
     */
    @ExceptionHandler(BizException.class)
    public Result serviceException(BizException e, HttpServletRequest request) {
        log.error("请求地址{}发生业务异常:", request.getRequestURI(), e);
        Integer statusCode = e.getStatusCode();
        return !IntegerUtils.isNull(statusCode) ?
                Result.ofFail(statusCode, showFullMessage ? e.getMessage() : BizFullMessage) :
                Result.ofFailMsg(showFullMessage ? e.getMessage() : BizFullMessage);
    }

    /**
     * 处理 NullPointerException
     */
    @ExceptionHandler(NullPointerException.class)
    public Result handleNullPointerException(NullPointerException e, HttpServletRequest request) {
        log.error("请求地址{}发生空指针:", request.getRequestURI(), e);
        return Result.ofFailMsg(showFullMessage ? e.getMessage() : NullFullMessage);
    }

    /**
     * 处理 RuntimeException
     */
    @ExceptionHandler(RuntimeException.class)
    public Result runtimeException(RuntimeException e, HttpServletRequest request) {
        log.error("请求地址{}运行时发生异常:", request.getRequestURI(), e);
        return Result.ofFailMsg(showFullMessage ? e.getMessage() : RuntimeFullMessage);
    }

    /**
     * 请求方式不支持
     */
    @ExceptionHandler(HttpRequestMethodNotSupportedException.class)
    public Result handleHttpRequestMethodNotSupported(HttpRequestMethodNotSupportedException e,
                                                      HttpServletRequest request) {
        String[] methods = e.getSupportedMethods();
        StringBuffer stringBuffer = new StringBuffer();
        if (methods != null) {
            stringBuffer.append(String.join("、", methods));
        }
        log.error("请求地址{}不支持{}请求,支持以下请求{}", request.getRequestURI(), e.getMethod(), stringBuffer);
        return Result.ofFailMsg(showFullMessage ? e.getMessage() : HttpRequestMethodNot);
    }

    /**
     * 处理 OutOfMemoryError
     */
    @ExceptionHandler(OutOfMemoryError.class)
    public Result handleOomException(OutOfMemoryError e, HttpServletRequest request) {
        log.error("请求地址{}发生内存不足错误{} ", request.getRequestURI(), e.getMessage());
        return Result.ofFailMsg(e.getMessage());
    }

    /**
     * 处理 Throwable 异常
     */
    @ExceptionHandler(Throwable.class)
    public Result<Void> handleThrowable(Throwable ex, HttpServletRequest request) {
        log.error("请求地址{}发生Throwable异常{} ", request.getRequestURI(), ex.getMessage());
        return Result.ofFailMsg(ex.getMessage());
    }

    /**
     * 处理 HttpMessageConversionException
     */
    @ExceptionHandler(HttpMessageConversionException.class)
    public Result handleHttpMessageConversionException(HttpMessageConversionException ex, HttpServletRequest request) {
        log.error("请求地址{}发生HttpMessageConversionException异常: ", request.getRequestURI(), ex.getMessage());
        return Result.ofFailMsg(ex.getMessage());
    }

    /**
     * 未知异常
     */
    @ExceptionHandler(Exception.class)
    public Result exception(Exception e, HttpServletRequest request) {
        log.error("请求地址{}发生未知异常:", request.getRequestURI(), e);
        return Result.ofFailMsg(showFullMessage ? e.getMessage() : ExceptionFullMessage);
    }

//    /**
//     * 权限校验异常
//     * 捕捉AccessDeniedException，spring security抛出的无权限访问的异常信息
//     *
//     * @param e
//     * @param request
//     * @return Result
//     */
//    @ExceptionHandler(AccessDeniedException.class)
//    public Result handleAccessDeniedException(AccessDeniedException e, HttpServletRequest request) {
//        log.error("请求地址{},权限校验失败{}", request.getRequestURI(), e.getMessage());
//        return Result.ofFailMsg(ACCESS_DENIED_MSG);
//    }
}
